pub use base64ct;
use field::{
    ComputeAction, VddFieldType, CA_REF_MOD, CA_REF_SUM, CA_VAL_AVG, CA_VAL_MAX, CA_VAL_MIN,
    CA_VAL_SUM, C_FT_AUTO_INCREASE, C_FT_AUTO_INCREASE_GLOBAL, C_FT_BOOL, C_FT_CODE, C_FT_COMPUTED,
    C_FT_DATE, C_FT_DATETIME, C_FT_FILE, C_FT_FLOAT, C_FT_MODEL, C_FT_MODEL_SELF, C_FT_TIME,
    C_FT_USERID, C_FT_USER_SELF, FT_INT, FT_JSON, FT_STRING, FT_YAML,
};
use query::{
    VddValueEvaluation, C_FVE_BETWEEN, C_FVE_END_WITH, C_FVE_EQ, C_FVE_IN, C_FVE_NOT_CONTAIN,
    C_FVE_NOT_EQ, C_FVE_NOT_IN, C_FVE_OUT_RANGE, C_FVE_PART_MATCH, C_FVE_START_WITH,
};
use record::{RecordRuleDetail, RR_CONSUME, RR_EVA, RR_UNIQUE};
use std::any::type_name;
use std::cmp;
use std::collections::HashMap;
use std::fmt::Debug;
use std::option::Option;
use std::str::FromStr;
use visit::{
    ShareRuleOfField, ShareRuleOfModel, VisitGroupType, SRF_ENC, SRF_HIDE, SRF_RO, SRM_REC_MAX,
    SRM_V_A, SRM_V_OV, SRM_V_OVS, VGT_ANONYMOUS, VGT_CODE, VGT_PUB_KEY,
};

pub mod field;
pub mod gateway;
pub mod hex;
pub mod i18n_text;
pub mod id_factory;
pub mod model;
pub mod proj;
pub mod query;
pub mod record;
#[cfg(test)]
mod test;
pub mod value;
pub mod visit;

use base64ct::{Base64, Encoding};
use rand::Rng;
use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePublicKey};
use rsa::{Pkcs1v15Encrypt, Pkcs1v15Sign, RsaPrivateKey, RsaPublicKey};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sha2::{Digest, Sha256};
use std::sync::{Arc, LazyLock};
use std::time::{SystemTime, UNIX_EPOCH};

pub const APP_ID: &str = "visit_dd";
pub const SECRET_KEY: &str = "ANYSOFT_2024";
pub const VERSION: &str = "0.3.0";

/// 订阅内容中的数据操作方式表示 1 新增 2修改 255(u8::max) 删除
pub const AC_DO_NOTHING: u8 = u8::MIN; // 不操作
pub const AC_ADD: u8 = 1; // 增加
pub const AC_EDIT: u8 = 2; // 修改
pub const AC_ADD_ITEM: u8 = 11; // 增加子项
pub const AC_EDIT_ITEM: u8 = 21; // 修改子项
pub const AC_EDIT_ITEM_BY_INDEX: u8 = 22; // 修改子项 根据下标
pub const AC_EDIT_ATTR: u8 = 23; // 修改某一属性
pub const AC_DELETE: u8 = u8::MAX; // 删除
pub const AC_DELETE_ITEM: u8 = AC_DELETE - 1; // 删除子项 254
pub const AC_DELETE_ITEM_BY_INDEX: u8 = AC_DELETE - 2; // 删除子项 根据下标 253
pub const AC_DELETE_ATTR: u8 = AC_DELETE - 3; // 删除对象某个属性 252

pub type Astr = Arc<str>;
pub type Ares = Result<(), Astr>;

pub fn bool_to_ares(b: bool) -> Ares {
    if b {
        Ok(())
    } else {
        Err("FALSE".into())
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq)]
pub struct UserId(pub u64);
pub const EMPTY_UID: UserId = UserId(0);
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
pub struct FieldId(pub u64);
pub const EMPTY_FID: FieldId = FieldId(0);
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq)]
pub struct RecordId(pub u64);
pub const EMPTY_RID: RecordId = RecordId(0);
pub const CACHE_LISTENER: UserId = UserId(9999);

#[macro_export]
macro_rules! i18n {
    ($content:expr) => {
        $crate::i18n_text::get_text(&$crate::i18n_text::TemplateKey($content))
    };
    ($content:expr, $($part:expr),*) => {
        $crate::i18n_text::get_and_format_text(&$crate::i18n_text::TemplateKey($content), &[$($part),*])
    }
}

#[derive(Debug, Serialize)]
pub struct CommonCode {
    pub code: u16,
    pub key: Astr,
    pub label: Astr,
}

pub const DT_FORMAT: &str = "%Y-%m-%d %H:%M:%S";
pub const T_FORMAT: &str = "%H:%M:%S";
pub const D_FORMAT: &str = "%Y-%m-%d";

pub mod datetime_format {
    use crate::DT_FORMAT;
    use chrono::NaiveDateTime;
    use serde::{self, Deserialize, Deserializer, Serializer};

    pub fn serialize<S>(date_time: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let s = format!("{}", date_time.format(DT_FORMAT));
        serializer.serialize_str(&s)
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<NaiveDateTime, D::Error>
    where
        D: Deserializer<'de>,
    {
        String::deserialize(deserializer)
            .map(|s| NaiveDateTime::parse_from_str(&s, DT_FORMAT).unwrap())
    }
}

pub mod option_datetime_format {
    use crate::DT_FORMAT;
    use chrono::NaiveDateTime;
    use serde::{self, Deserialize, Deserializer, Serializer};

    pub fn serialize<S>(date_time: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if date_time.is_none() {
            serializer.serialize_str("")
        } else {
            let ts = date_time.unwrap();
            let s = format!("{}", ts.format(DT_FORMAT));
            serializer.serialize_str(&s)
        }
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<NaiveDateTime>, D::Error>
    where
        D: Deserializer<'de>,
    {
        Option::<String>::deserialize(deserializer).map(|s| {
            if s.is_some() {
                let dt = NaiveDateTime::parse_from_str(&s.unwrap(), DT_FORMAT);
                if dt.is_ok() {
                    return Some(dt.unwrap());
                }
            }
            None
        })
    }
}

#[derive(Serialize)]
pub struct ActionReturnMessage<T> {
    pub ok: bool,
    pub data: T,
    pub error: Option<Astr>,
}

impl<T: Sized + Serialize> ActionReturnMessage<T> {
    pub fn ok(t: T) -> Self {
        Self {
            ok: true,
            data: t,
            error: None,
        }
    }
    pub fn error(t: T, message: &str) -> Self {
        Self {
            ok: false,
            data: t,
            error: Some(Arc::from(message)),
        }
    }
}

impl ActionReturnMessage<()> {
    pub fn from_ares(ares: Ares) -> Self {
        match ares {
            Ok(()) => Self::ok(()),
            Err(e) => Self::error((), &e),
        }
    }
}

pub struct ProjectRsaHelper {
    pub prik: RsaPrivateKey,
    pub pubk: RsaPublicKey,
}

impl ProjectRsaHelper {
    pub fn init(private_key: &str, public_key: &str) -> Self {
        Self {
            prik: RsaPrivateKey::from_pkcs8_pem(private_key).unwrap(),
            pubk: RsaPublicKey::from_public_key_pem(public_key).unwrap(),
        }
    }

    pub fn encode(&self, content: &[u8]) -> String {
        let b_v = self
            .prik
            .sign(Pkcs1v15Sign::new_unprefixed(), content)
            .unwrap();
        Base64::encode_string(&b_v)
    }

    pub fn decode_b64str(&self, b64str: &str) -> Result<String, Astr> {
        let content = Base64::decode_vec(b64str);
        if content.is_err() {
            return Err(i18n!(104, &content.unwrap_err().to_string()));
        }
        let content = content.unwrap();
        // println!("{}", content.len());
        let mut i = 0;
        let mut content2: Vec<u8> = Vec::new();
        while i < content.len() {
            let end_idx = cmp::min(i + 256, content.len());
            // println!("{},{}", i, end_idx);
            let sub = &content[i..end_idx];
            // println!("{:?}",&sub);
            let b_v = self.prik.decrypt(Pkcs1v15Encrypt, &sub);
            if b_v.is_err() {
                return Err(i18n!(105, &b_v.unwrap_err().to_string()));
            }
            let mut b_v = b_v.unwrap();
            content2.append(&mut b_v);
            i = end_idx;
        }
        Ok(String::from_utf8(content2).unwrap())
    }

    pub fn get_pub_key(&self) -> Astr {
        Arc::from(Base64::encode_string(
            self.pubk.clone().to_public_key_der().unwrap().as_bytes(),
        ))
    }
}

pub trait JsonSupportTrait {
    ///
    fn has_useful_str(&self, field: &str) -> bool;
    ///
    fn has_useful_int(&self, field: &str) -> bool;
    fn try_hard_to_i64(&self) -> Option<i64>;
    fn try_hard_to_f64(&self) -> Option<f64>;
}

impl JsonSupportTrait for Value {
    ///
    fn has_useful_str(&self, field: &str) -> bool {
        let b1 = self[field].as_str().is_some();
        if !b1 {
            false
        } else {
            b1 && !self[field].as_str().unwrap().is_empty()
        }
    }

    ///
    fn has_useful_int(&self, field: &str) -> bool {
        let b1 = self[field].as_u64().is_some();
        if !b1 {
            false
        } else {
            let b2 = self[field].as_u64().unwrap() > 0;
            let b3 = self[field].as_i64().is_some();
            b1 && (b2 || b3)
        }
    }

    fn try_hard_to_i64(&self) -> Option<i64> {
        if self.is_i64() {
            return self.as_i64();
        } else if self.is_u64() {
            return Some(self.as_u64()? as i64);
        } else if self.is_string() {
            let converted = i64::from_str(self.as_str()?);
            return if converted.is_ok() {
                Some(converted.unwrap())
            } else {
                None
            };
        }
        None
    }

    fn try_hard_to_f64(&self) -> Option<f64> {
        if self.is_f64() {
            return self.as_f64();
        } else if self.is_i64() {
            return Some(self.as_i64()? as f64);
        } else if self.is_u64() {
            return Some(self.as_u64()? as f64);
        } else if self.is_string() {
            let converted = f64::from_str(self.as_str()?);
            return if converted.is_ok() {
                Some(converted.unwrap())
            } else {
                None
            };
        }
        None
    }
}

/// 系统运行时的缓存数据包装器
#[derive(Debug)]
pub struct RuntimeCache<T> {
    pub ts: u64,
    pub data: T,
}

impl<T> RuntimeCache<T> {
    pub fn from(data: T) -> Self {
        Self {
            ts: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs(),
            data,
        }
    }
    /// 判断缓存内容是否过期，判断依据2分钟
    pub fn test_alive(&self, limit_seconds: u16) -> bool {
        SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs()
            - self.ts
            < limit_seconds as u64
    }
}

pub fn to_sha256_hash(source: impl AsRef<[u8]>) -> Astr {
    let hash = Sha256::digest(source);
    Arc::from(hex::encode(hash[..].to_vec()))
}

pub fn to_sha256_hash_bin(source: impl AsRef<[u8]>) -> Vec<u8> {
    let hash = Sha256::digest(source);
    hash[..].to_vec()
}

/// 从key中提取最后一个子key
pub fn extract_last_str_from_key(key: &str) -> Astr {
    let s = key.split("/").last().unwrap_or("");
    Arc::from(s)
}

/// 从racksdb的键中提取最后一个分割符后面的字符串，转成u64数字
pub fn extract_u64_from_key(s: &str) -> u64 {
    s.split("/")
        .collect::<Vec<&str>>()
        .last()
        .map(|x| u64::from_str(x).unwrap_or(0))
        .unwrap_or(0)
}

/// 校验上传上来的字段码数组是否是全部字段码的子集
pub fn is_sub_vec(tags: &[Astr], all_tag: &HashMap<u64, Astr>) -> bool {
    if tags.is_empty() {
        return false;
    }
    // println!("{:?}",code_map);
    let mut count_map: HashMap<Astr, i8> = HashMap::new();
    all_tag.iter().for_each(|item| {
        count_map.insert(item.1.to_owned(), 1);
    });
    for tag in tags {
        if count_map.contains_key(tag) {
            count_map.insert(tag.to_owned(), 2);
        } else {
            // tags 中出现了不在 all_tag 里的 tag
            return false;
        }
    }
    // println!("{:?}",count_map);
    count_map.retain(|_, v| *v < 2);
    count_map.len() != all_tag.len()
}

/// 从source中生成符合长度的随机字符串
pub fn random_str_form(len: u8, source: &[u8]) -> String {
    let mut rng = rand::thread_rng();
    (0..len)
        .map(|_| {
            let idx = rng.gen_range(0..source.len());
            source[idx] as char
        })
        .collect::<String>()
}

pub fn random_az_str(len: u8) -> String {
    random_str_form(len, visit::CHARSET)
}

/// 将包含短句子的数据进行join操作
pub fn astr_ary_join(ary: &[Astr]) -> Astr {
    let mut r = String::new();
    ary.iter().for_each(|x| {
        r.push_str(x);
        r.push_str(",");
    });
    r.pop();
    Arc::from(r)
}

pub trait SqlAttribute {
    /// 判断字段值在形成sql部分时是否需要用括号包装
    fn quote_value(&self) -> bool;
}

pub static TYPE_DICT: LazyLock<Vec<(&'static str, u16, &'static str, Astr)>> =
    LazyLock::new(|| {
        let mut r = Vec::<(&'static str, u16, &'static str, Astr)>::new();
        r.push((
            type_name::<VddFieldType>(),
            FT_STRING,
            "FtString",
            i18n!(1211),
        ));
        r.push((type_name::<VddFieldType>(), FT_JSON, "FtJson", i18n!(1223)));
        r.push((type_name::<VddFieldType>(), FT_YAML, "FtYaml", i18n!(1224)));
        r.push((type_name::<VddFieldType>(), FT_INT, "FtInt", i18n!(1212)));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_FLOAT,
            "FtFloat",
            i18n!(1213),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_BOOL,
            "FtBool",
            i18n!(1214),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_AUTO_INCREASE,
            "FtAutoIncreaseInt",
            i18n!(1247),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_AUTO_INCREASE_GLOBAL,
            "FtAutoIncreaseIntGlobal",
            i18n!(1248),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_DATE,
            "FtDate",
            i18n!(1215),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_TIME,
            "FtTime",
            i18n!(1216),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_DATETIME,
            "FtDateTime",
            i18n!(1217),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_FILE,
            "FtFile",
            i18n!(1218),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_COMPUTED,
            "FtComputed",
            i18n!(1219),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_CODE,
            "FtCode",
            i18n!(1220),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_MODEL,
            "FtModel",
            i18n!(1221),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_MODEL_SELF,
            "FtModelSelf",
            "本模型的记录引用".into(),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_USERID,
            "FtUserId",
            i18n!(1222),
        ));
        r.push((
            type_name::<VddFieldType>(),
            C_FT_USER_SELF,
            "FtUserSelf",
            "当前用户".into(),
        ));
        r.push((type_name::<ShareRuleOfField>(), 0, SRF_HIDE, i18n!(1311)));
        r.push((type_name::<ShareRuleOfField>(), 0, SRF_RO, i18n!(1312)));
        r.push((type_name::<ShareRuleOfField>(), 0, SRF_ENC, i18n!(1313)));
        r.push((type_name::<VisitGroupType>(), 0, VGT_ANONYMOUS, i18n!(1321)));
        r.push((type_name::<VisitGroupType>(), 0, VGT_PUB_KEY, i18n!(1322)));
        r.push((type_name::<VisitGroupType>(), 0, VGT_CODE, i18n!(1324)));
        r.push((type_name::<ShareRuleOfModel>(), 0, SRM_V_A, i18n!(1332)));
        r.push((type_name::<ShareRuleOfModel>(), 0, SRM_V_OVS, i18n!(1333)));
        r.push((type_name::<ShareRuleOfModel>(), 0, SRM_V_OV, i18n!(1334)));
        r.push((
            type_name::<ShareRuleOfModel>(),
            0,
            SRM_REC_MAX,
            "最多存放记录数".into(),
        ));
        r.push((type_name::<ComputeAction>(), 0, CA_REF_SUM, i18n!(1241)));
        r.push((type_name::<ComputeAction>(), 0, CA_REF_MOD, i18n!(1242)));
        r.push((type_name::<ComputeAction>(), 0, CA_VAL_MAX, i18n!(1243)));
        r.push((type_name::<ComputeAction>(), 0, CA_VAL_MIN, i18n!(1244)));
        r.push((type_name::<ComputeAction>(), 0, CA_VAL_SUM, i18n!(1245)));
        r.push((type_name::<ComputeAction>(), 0, CA_VAL_AVG, i18n!(1246)));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_EQ,
            "等于".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_NOT_EQ,
            "不等于".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_PART_MATCH,
            "包含".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_START_WITH,
            "以此开头".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_END_WITH,
            "以此结尾".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_NOT_CONTAIN,
            "不包含".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_BETWEEN,
            "范围内".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_OUT_RANGE,
            "范围外".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_IN,
            "属于值集合".into(),
        ));
        r.push((
            type_name::<VddValueEvaluation>(),
            0,
            C_FVE_NOT_IN,
            "不属于值集合".into(),
        ));
        r.push((
            type_name::<RecordRuleDetail>(),
            0,
            RR_UNIQUE,
            "组合值唯一".into(),
        ));
        r.push((
            type_name::<RecordRuleDetail>(),
            0,
            RR_CONSUME,
            "引用次数限制".into(),
        ));
        r.push((
            type_name::<RecordRuleDetail>(),
            0,
            RR_EVA,
            "满足字段值规则".into(),
        ));
        r
    });

pub fn search_type_name(cf: &str, key: &str) -> Astr {
    TYPE_DICT
        .iter()
        .find(|item| item.0 == cf && item.2 == key)
        .map(|item| item.3.clone())
        .unwrap_or("".into())
}

pub fn search_type_id(cf: &str, key: &str) -> u16 {
    TYPE_DICT
        .iter()
        .find(|item| item.0 == cf && item.2 == key)
        .map(|item| item.1)
        .unwrap_or(0)
}
